package com.blue.alipay.utils.http;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 描述 http util
 * 时间 2017-9-22 11:03
 * 作者 肖亦鸣
 */
public class HttpClientsUtil {

    private final static Logger logger = LogManager.getLogger(HttpClientsUtil.class);

    private final static int SOCKET_TIMEOUT = 6000;
    private final static int CONNECT_TIMEOUT = 6000;

    private final static PoolingHttpClientConnectionManager connectionManager;
    private static HttpClientBuilder httpBuilder = null;
    private static RequestConfig requestConfig = null;
    private static final int MAX_CONNECTIONS_SIZE = 200;
    private static final int DEF_MAX_PER_ROUTE = 50;

    public static final String APPLICATION_JSON = "application/json";
    public static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded";

    static {
        connectionManager = new PoolingHttpClientConnectionManager();
        connectionManager.setMaxTotal(MAX_CONNECTIONS_SIZE);
        connectionManager.setDefaultMaxPerRoute(DEF_MAX_PER_ROUTE);
        requestConfig = RequestConfig.custom().setSocketTimeout(SOCKET_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).build();
        httpBuilder = HttpClients.custom();
        httpBuilder.setConnectionManager(connectionManager);
    }

    public static HttpClientConnectionManager getPoolconnmanager() {
        return connectionManager;
    }

    // 获取连接
    private static CloseableHttpClient getConnection() {
        return httpBuilder.build();
    }

    /**
     * 构造post请求，发送请求
     *
     * @param url
     * @param params
     * @return
     */
    public static String httpClientPost(String url, Map<String, String> params) {
        HttpClient httpclient;
        HttpPost httpost = null;
        try {
            httpclient = getConnection();
            List<BasicNameValuePair> formParams = new ArrayList<BasicNameValuePair>();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            httpost = new HttpPost(url);
            // 设置请求和传输超时时间
            httpost.setConfig(requestConfig);
            httpost.setEntity(new UrlEncodedFormEntity(formParams, "UTF-8"));
            return invoke(httpclient, httpost);
        } catch (IOException ex) {
            logger.error("", ex);
        } finally {
            if (httpost != null) {
                httpost.releaseConnection();
            }
        }
        return null;
    }

    /**
     * 构造post请求，发送请求
     *
     * @param url
     * @param body
     * @return
     */
    public static String httpClientPost(String url, String body) {
        CloseableHttpClient httpclient;
        HttpPost httpost = null;
        try {
            httpclient = getConnection();
            httpost = new HttpPost(url);
            // 设置请求和传输超时时间
            httpost.setConfig(requestConfig);
            StringEntity sey = new StringEntity(body, Charset.forName("UTF-8"));
            httpost.setEntity(sey);
            return invoke(httpclient, httpost);
        } catch (Exception ex) {
            logger.error("", ex);
        } finally {
            if (httpost != null) {
                httpost.releaseConnection();
            }
        }
        return null;
    }

    /**
     * 构造post请求，发送请求
     *
     * @param url
     * @param body
     * @return
     */
    public static String httpClientPost(String url, String body, String contentType) {
        CloseableHttpClient httpclient;
        HttpPost httpost = null;
        try {
            httpclient = getConnection();
            httpost = new HttpPost(url);
            // 设置请求和传输超时时间
            httpost.setConfig(requestConfig);
            StringEntity stringEntity = new StringEntity(body, Charset.forName("UTF-8"));
            stringEntity.setContentType(contentType);
            httpost.setEntity(stringEntity);
            return invoke(httpclient, httpost);
        } catch (Exception ex) {
            logger.error("", ex);
        } finally {
            if (httpost != null) {
                httpost.releaseConnection();
            }
        }
        return null;
    }

    /**
     * 发送请求
     *
     * @param httpClient
     * @param httpRequest
     * @return
     */
    private static String invoke(HttpClient httpClient, HttpUriRequest httpRequest) {
        HttpResponse response = null;
        HttpEntity httpEntity = null;
        try {
            response = httpClient.execute(httpRequest);
            if (response == null) {
                return "";
            }
            httpEntity = response.getEntity();
            if (response.getStatusLine().getStatusCode() == 200) {
                String ret = EntityUtils.toString(httpEntity, Charset.forName("utf-8"));
                if (ret == null) {
                    return "";
                }
                logger.debug("http响应,status:" + response.getStatusLine().getStatusCode() + ",body:" + ret);
                return ret;
            } else {
                String ret = EntityUtils.toString(httpEntity, Charset.forName("utf-8"));
                logger.error("http响应,status:" + response.getStatusLine().getStatusCode() + ",body:" + ret);
                return null;
            }
        } catch (NoHttpResponseException e) {
            logger.error("URI:" + httpRequest.getURI() + " NoHttpResponse error. ");
        } catch (IOException e) {
            logger.error("URI:" + httpRequest.getURI(), e);
        } finally {
            if (httpEntity != null) {
                try {
                    EntityUtils.consume(httpEntity);
                } catch (IOException e) {
                    logger.error("流关闭失败!", e);
                }
            }
        }
        return null;
    }

    /**
     * get请求
     *
     * @param url
     * @return
     */
    public static String httpClientGet(String url) {
        CloseableHttpClient httpClient;
        HttpGet httpGet = null;
        try {
            httpClient = getConnection();
            httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);
            return invoke(httpClient, httpGet);
        } catch (Exception ex) {
            logger.error("", ex);
        } finally {
            if (httpGet != null) {
                httpGet.releaseConnection();
            }
        }
        return null;
    }

    /**
     * get请求
     *
     * @param url
     * @return
     */
    public static boolean httpClientGetToFile(String url, String savePath) {
        CloseableHttpClient httpClient;
        HttpGet httpGet = null;
        try {
            httpClient = getConnection();
            httpGet = new HttpGet(url);
            httpGet.setConfig(requestConfig);

            HttpResponse response = null;
            HttpEntity httpEntity = null;
            try {
                response = httpClient.execute(httpGet);
                if (response == null) {
                    return false;
                }
                httpEntity = response.getEntity();
                if (response.getStatusLine().getStatusCode() == 200) {
                    new File(savePath).delete();
                    Files.copy(httpEntity.getContent(), Paths.get(savePath));
                    return true;
                } else {
                    String ret = EntityUtils.toString(httpEntity, Charset.forName("utf-8"));
                    logger.error("http响应,status:" + response.getStatusLine().getStatusCode() + ",body:" + ret);
                    return false;
                }
            } catch (IOException ex) {
                logger.error("", ex);
            } finally {
                if (httpEntity != null) {
                    try {
                        EntityUtils.consume(httpEntity);
                    } catch (IOException e) {
                        logger.error("流关闭失败!", e);
                    }
                }
            }
            return false;

        } catch (Exception ex) {
            logger.error("", ex);
        } finally {
            if (httpGet != null) {
                httpGet.releaseConnection();
            }
        }
        return false;
    }

    /**
     * 发起ssl post请求
     *
     * @param sslsf
     * @param url
     * @param body
     * @return
     */
    public static String httpClientSLLPost(SSLConnectionSocketFactory sslsf, String url, String body) {
        HttpClientBuilder httpSLLBulder = HttpClients.custom().setSSLSocketFactory(sslsf);
        httpBuilder.setConnectionManager(connectionManager);
        CloseableHttpClient httpclient = httpSLLBulder.build();
        HttpPost httpPost = null;
        StringEntity reqEntity;
        try {
            httpPost = new HttpPost(url);
            reqEntity = new StringEntity(body, Charset.forName("utf-8"));
            reqEntity.setContentType("application/x-www-form-urlencoded");
            httpPost.setEntity(reqEntity);
            return invoke(httpclient, httpPost);
        } catch (Exception ex) {
            logger.error("", ex);
        } finally {
            if (httpPost != null) {
                httpPost.releaseConnection();
            }
        }
        return "";
    }

    public static InputStream String2Inputstream(String str) {
        return new ByteArrayInputStream(str.getBytes());
    }
}
